package com.ruyue.csinstall.model.quote;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.util.FileCopyUtils;

/**
 * 默认的通讯机应用加载器
 */
public class DefaultAppLoader implements AppLoader, ResourceLoaderAware {
    private static final Log log =LogFactory.getLog(DefaultAppLoader.class);
    //
    private ClassLoader parent;
    //
    //private Set<File> appFiles = new HashSet<File>();
    private ResourcePatternResolver resourcePatternResolver;

    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
    }

    public void setClassLoader(ClassLoader parent) {
        this.parent = parent;
    }

    public AppMetadata load(File appFile,File deployDirectory) throws IOException {
    	//
    	if(appFile.isFile() && appFile.getName().endsWith(".zip")) {
    		return loadAppFromZipFile(appFile, deployDirectory);
    	} else if(appFile.isDirectory()) {
    		return loadAppFromDirectory(appFile);
    	}
    	throw new UnsupportedOperationException("不支持的应用格式：" + appFile.getCanonicalPath());
    }

    protected AppMetadata loadAppFromDirectory(File appFile) throws IOException {
        //
        File[] fileJars = appFile.listFiles(new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.endsWith(".jar");
            }
        });
        if (fileJars == null){
        	return null;
        }
        //
        URL[] jarUrls = new URL[fileJars.length];
        for(int i=0; i<jarUrls.length; i++) {
            jarUrls[i] = fileJars[i].toURI().toURL();
        }
        //
        AppClassLoader appClassLoader = new AppClassLoader(jarUrls, parent);
        //
        AppMetadata appMetadata = new DefaultAppMetadata(appFile, appClassLoader);
        //
        return appMetadata;
    }

    protected AppMetadata loadAppFromZipFile(File appFile,File deploysDirectory) throws IOException {
    	//
    	if(log.isInfoEnabled()) {
    		log.info(String.format("开始部署扫描到的应用 [%s]", appFile.getAbsolutePath()));
    	}
    	File appDeployDirectory = new File(deploysDirectory,appFile.getName().substring(0, appFile.getName().indexOf(".zip")));
    	//
    	//
    	ZipFile zipFile = new ZipFile(appFile);
    	for(Enumeration<? extends ZipEntry> e = zipFile.entries(); e.hasMoreElements();) {
    		ZipEntry zipEntry = e.nextElement();
    		// skip directory copy
    		if(zipEntry.isDirectory()) {
    			continue;
    		}
    		// create copy target file
    		File target = new File(deploysDirectory, zipEntry.getName());
    		if(target.exists()==false) {
				if (!target.getParentFile().exists() && !target.getParentFile().mkdirs()) {
					throw new IOException(String.format("创建目录[%s]失败", target.getParent()));
				}
				if (!target.createNewFile()) {
					throw new IOException(String.format("创建文件[%s]失败", target.getAbsolutePath()));
				}
    		}
    		// copy from input stream to output stream
    		InputStream inputStream = zipFile.getInputStream(zipEntry);
    		OutputStream outputStream = new FileOutputStream(target);
    		FileCopyUtils.copy(inputStream, outputStream);
    	}
    	zipFile.close();
    	//
    	//
    	if(log.isInfoEnabled()) {
    		log.info(String.format("应用 [%s] 已成功部署到 [%s]", appFile.getAbsolutePath(), appDeployDirectory.getAbsolutePath()));
    	}
    	//
    	return loadAppFromDirectory(appDeployDirectory);
    }

}